using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using System.Xml.Xsl;
using System.Xml;
using System.IO;

namespace MailProgramma
{
    class Mail
    {
		public const string ImagesPath = "./mail-machine/images/";
		public const string BijlagePath = "./mail-machine/bijlages/";
		
		public StringCollection attachments;
		
        private XslCompiledTransform tHtml, tText, tDirty;

        public Mail(string xslHtml, string xslText, string xslDirty)
        {
            tHtml = new XslCompiledTransform();
            tHtml.Load(xslHtml);
            tText = new XslCompiledTransform();
            tText.Load(xslText);
            tDirty = new XslCompiledTransform();
            tDirty.Load(xslDirty);
        }

        public void CreateHtmls(XmlElement input)
        {
            //string outfile = input.GetAttribute("title"); //TODO
            string outfile = "./mail-machine/out";

			string cleanFilename = System.IO.Path.GetFileName(input.GetAttribute("url"));
            //1. generate clean html
            XmlTextWriter html = new XmlTextWriter("./mail-machine/" + cleanFilename, Encoding.UTF8);
            tHtml.Transform(input, html);
            html.Flush();
            html.Close();
                        
            //2. generate dirty html, text, using images
            XmlTextWriter text = new XmlTextWriter(outfile + ".txt", Encoding.UTF8); //todo Unicode?
            tText.Transform(input, text);
            text.Flush();
            text.Close();
            XmlTextWriter dirty = new XmlTextWriter(outfile + ".dirty.html", Encoding.UTF8);
            tDirty.Transform(input, dirty);
            dirty.Flush();
            dirty.Close();
        }

        public MailMessage CreateMailMessage(XmlElement input)
        {
            //string outfile = input.GetAttribute("title"); //TODO
            string outfile = "./mail-machine/out";

            MailAddress me = new MailAddress(input.GetAttribute("my-mail"), input.GetAttribute("my-name"));

            MailMessage ret = new MailMessage();
            ret.From = me;
            //ret.ReplyTo = me;
            //ret.Sender = me;

            ret.Subject = input.GetAttribute("title");


            //tt.CharSet = "...";
            AlternateView text = new AlternateView(outfile + ".txt", MediaTypeNames.Text.Plain);
            text.TransferEncoding = TransferEncoding.QuotedPrintable;
            ret.AlternateViews.Add(text);


            StringCollection attachmentPaths = new StringCollection();

            //include not-absolute (http) referenced images
            XmlNodeList files = input.SelectNodes("//@*[name()='separator-img' or name()='src' or name()='header-image' or name()='image' or name()='icon']");
            for (int i = 0; i < files.Count; i++)
            {
                string href = files[i].Value; //todo check unique paths?

                if (!href.StartsWith("http:"))
                {
                    if (!attachmentPaths.Contains(href)) attachmentPaths.Add(href);

                    //replace the path by the id!
                    files[i].Value = "cid:" + href; //path is used as id
                }
            }

            //ret.IsBodyHtml = true;
            //ret.Body = File.ReadAllText(outfile + ".dirty.html");
            //ret.BodyEncoding = Encoding.Unicode;

            //ht.CharSet = "...";
            //compile dirty html again for embedded images
            //MemoryStream temp = new MemoryStream();
            XmlTextWriter dirty = new XmlTextWriter(outfile + ".dirty.temp.html", Encoding.UTF8); //todo Unicode?
            tDirty.Transform(input, dirty);
            dirty.Flush(); //write it to temp
            dirty.Close();
            //temp.WriteTo(File.Create(outfile + ".dirty.temp.html")); //for debug
            AlternateView html = new AlternateView(outfile + ".dirty.temp.html", MediaTypeNames.Text.Html);
            ret.AlternateViews.Add(html);
            html.TransferEncoding = TransferEncoding.QuotedPrintable;
            foreach(string path in attachmentPaths)
            {
                ContentType contentType = new ContentType();
	            if (path.ToLower().EndsWith(".gif"))
	                contentType.MediaType = "image/gif";
	            else if (path.ToLower().EndsWith(".png"))
	                contentType.MediaType = "image/png";
	            else if (path.ToLower().EndsWith(".jpg"))
	                contentType.MediaType = "image/jpeg";
	            
				string path1 = Mail.ImagesPath + path;
				Console.WriteLine("toevoegen bestand: " + path1);
	            LinkedResource attach = new LinkedResource(path1, contentType);
	           //attach.TransferEncoding = TransferEncoding.Base64;
                attach.ContentId = path;
                html.LinkedResources.Add(attach);
            }
			this.attachments = attachmentPaths;


			ret.BodyEncoding = System.Text.Encoding.UTF8;
            return ret; //can set priority, set recipients, ...
        }

        public void Send(XmlElement input, string recipients)
        {
            MailMessage message = CreateMailMessage(input);
            //message.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;
            //message.ReplyTo = me;
            //message.Sender = me;
            //message.Priority = MailPriority.High;
            //message.Headers
            //message.Attachments
            message.Bcc.Add(recipients);
			string bijlage = input.GetAttribute("bijlage");
			if(bijlage != "")
			{
				Attachment a = new Attachment(Mail.BijlagePath + bijlage);
				a.Name = bijlage;
				message.Attachments.Add(a);
			}
			
            SmtpClient smtp = new SmtpClient(SmtpServer);
            try
            {
                smtp.Send(message);
				int count = recipients.Split(',').Length;
				if(count == 1)
					Console.WriteLine("Mail verzonden naar " + count + " persoon");
				else
					Console.WriteLine("Mail verzonden naar " + count + " personen");
            }
            catch(SmtpException e)
            {
                Console.WriteLine("SMTP: " + e.Message);
				throw;
            }
        }
		
		
		///<summary>Returns the smtp server to send the mail to</summary>
		private static string SmtpServer
		{
			get
			{
				string smtpServer = System.Configuration.ConfigurationManager.AppSettings["smtp-server"];
				//if(smtpServer == null)
					//smtpServer = "smtp.kliksafe.nl";
				
				return smtpServer;
			}
		}
    }
}
